package com.sinodata.bsm.center.engine.event.correlation;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.sinodata.bsm.center.cache.EventCorrelationPolicyCache;
import com.sinodata.bsm.center.cache.NewEventCache;
import com.sinodata.bsm.center.service.event.EventCorrelationPolicyService;
import com.sinodata.bsm.center.service.event.EventCorrelationService;
import com.sinodata.bsm.center.util.spring.SpringContextHolder;
import com.sinodata.bsm.common.constants.EventConstants;
import com.sinodata.bsm.common.vo.Event;
import com.sinodata.bsm.common.vo.EventCorrelation;
import com.sinodata.bsm.common.vo.EventCorrelationPolicy;

/**
 * 
 * <p>
 * Description: 事件相关性分析
 * </p>
 *
 * @author liulibo
 * @version 1.0

 * <p>
 * History: 
 *
 * Date                     Author         Version     Description
 * ---------------------------------------------------------------------------------
 * 2012-6-14 PM 9:40:06     liulibo        1.0         To create
 * </p>
 *
 * @since 
 * @see
 */
public class EventCorrelationManager {

    EventCorrelationService eventCorrelationService = SpringContextHolder.getBean(EventCorrelationService.class);

    EventCorrelationPolicyService eventCorrelationPolicyService = SpringContextHolder.getBean(EventCorrelationPolicyService.class);

    EventCorrelationPolicyCache eventCorrelationPolicyCache = SpringContextHolder.getBean(EventCorrelationPolicyCache.class);

    NewEventCache newEventCache = SpringContextHolder.getBean(NewEventCache.class);

    private static Logger logger = Logger.getLogger(EventCorrelationManager.class);
    private static EventCorrelationManager instance = null;
    String STATUS_START = "1";
    String STATUS_STOP = "0";
    Map<String, ECPInstance> ecpInstanceMap = new HashMap<String, ECPInstance>();
    List<ECPHandler> handlerList = new ArrayList<ECPHandler>();

    private EventCorrelationManager() {
        try {
            loadPolicy();
            processCache();
            logger.info("[TIP]\t EventCorrelationManager started!");
        } catch (Exception e) {
            logger.error("load ecp failed!", e);
        }
    }

    public static EventCorrelationManager getInstance() {
        if (instance == null) {
            instance = new EventCorrelationManager();
            (new ClearThread()).start();
        }
        return instance;
    }

    public Map<String, ECPInstance> getInstanceMap() {
        return ecpInstanceMap;
    }

    /**
     * 加载策略
     * @return
     * @throws Exception 
     */
    private boolean loadPolicy() throws Exception {
        List<EventCorrelationPolicy> ecpList = eventCorrelationPolicyService.getActiveEventCorrelationPolicys();
        if (ecpList == null) {
            return true;
        }
        for (EventCorrelationPolicy ecp : ecpList) {
            ECPHandler handler = new ECPHandler();
            handler.setEcp(ecp);
            handler.setEcpInstanceMap(ecpInstanceMap);
            handlerList.add(handler);
        }
        return true;
    }

    /**
     * 第一次启动的时候需要将所有缓存新事件处理一遍 
     */
    private void processCache() {
        List<Event> list = newEventCache.getAllNewEvents();
        for (Event value : list) {
            for (ECPHandler handler : handlerList) {
                //缓存处理不用进行延迟告警处理
                List<EventCorrelation> valueList = handler.handleEvent(value);
                //事件关联入库
                if (valueList != null) {
                    for (EventCorrelation ecValue : valueList) {
                        try {
                            eventCorrelationService.add(ecValue);
                        } catch (Exception e) {
                            logger.warn("Has a wrong on save EC:", e);
                        }
                    }
                }
            }
        }
    }

    /**
     * 处理入口
     * 
     * @param event
     */
    public synchronized void processEvent(Event event) {
        //不处理恢复事件
        if (event.getCatalog() == EventConstants.CATALOG_REFAULTEVENT) {
            return;
        }
        int notifyDelayTime = ECPHandler.NOTIFY_DEFAULT;

        //定义不需要告警的事件列表
        List<String> clearNotifyEvents = new ArrayList<String>();

        for (ECPHandler handler : handlerList) {
            List<EventCorrelation> valueList = handler.handleEvent(event);
            if (valueList == null || valueList.size() == 0) {
                continue;
            }
            //如果上次无值，或未匹配，则设置本次值

            if (notifyDelayTime == ECPHandler.NOTIFY_DEFAULT) {
                notifyDelayTime = handler.getAlarmDelayTime();
            }

            if (notifyDelayTime == ECPHandler.NOTIFY_MUST || handler.getAlarmDelayTime() == ECPHandler.NOTIFY_MUST) {
                notifyDelayTime = ECPHandler.NOTIFY_MUST;
            } else if (notifyDelayTime == ECPHandler.NOTIFY_NO || handler.getAlarmDelayTime() == ECPHandler.NOTIFY_NO) {
                notifyDelayTime = ECPHandler.NOTIFY_NO;
            }
            //采用最低延迟
            else if (notifyDelayTime > ECPHandler.NOTIFY_DEFAULT && handler.getAlarmDelayTime() > ECPHandler.NOTIFY_DEFAULT) {
                notifyDelayTime = notifyDelayTime < handler.getAlarmDelayTime() ? notifyDelayTime : handler.getAlarmDelayTime();
            }

            //事件关联入库
            for (EventCorrelation value : valueList) {
                try {
                    eventCorrelationService.add(value);
                    //将从事件加入到不需告警列表
                    if (!clearNotifyEvents.contains(value.getEventId() + "")) {
                        clearNotifyEvents.add(value.getEventId() + "");
                    }
                } catch (Exception e) {
                    logger.warn("Has a wrong on save EC:", e);
                }
            }
        }

        delayAlarm(event, notifyDelayTime);

        for (String item : clearNotifyEvents) {
            NotifyDelayer.getInstance().removeEvent(item);
        }
    }

    /**
     * 变更策略信息
     * 新增、修改、删除时需要维护handlerList
     * @param valueList
     */
    public synchronized void changeECPStatus() {//List<EventCorrelationPolicy> valueList
        List<EventCorrelationPolicy> valueList = eventCorrelationPolicyCache.getActiveEcps();
        //已经删除的策略，需要清除处理器
        List<ECPHandler> removeList = new ArrayList<ECPHandler>();
        removeList.addAll(handlerList);

        for (EventCorrelationPolicy value : valueList) {
            boolean inHandlerList = false;
            for (ECPHandler handler : handlerList) {
                if (handler.getEcp().getId().longValue() == value.getId().longValue()) {
                    inHandlerList = true;
                    if (STATUS_START.equals(value.getStatus())) {
                        //启用
                        handler.setEcp(value);
                    } else {
                        //禁用
                        handlerList.remove(handler);
                    }
                    //需要删除的handler
                    removeList.remove(handler);
                }
            }
            /**
             * 需要新增的EventCorrelationPolicy
             */
            if (!inHandlerList) {
                if (STATUS_START.equals(value.getStatus())) {
                    ECPHandler handler = new ECPHandler();
                    handler.setEcp(value);
                    handler.setEcpInstanceMap(ecpInstanceMap);
                    //添加handler
                    handlerList.add(handler);
                }
            }
        }

        //清除删除的策略处理器
        handlerList.removeAll(removeList);

        //重新处理事件
        ecpInstanceMap.clear();
        processCache();
    }

    /**
     * 压制事件通知
     * @param event
     * @param ecp
     * @return
     */
    protected boolean delayAlarm(Event event, long time) {
        if (time == ECPHandler.NOTIFY_MUST || time == ECPHandler.NOTIFY_DEFAULT) {
            return false;
        } else if (time == ECPHandler.NOTIFY_NO) {
            NotifyDelayer.getInstance().addNoAlarmEvent(event);
            return false;
        }
        NotifyDelayer.getInstance().addEvent(event, System.currentTimeMillis() + time * 1000);
        return true;
    }

}

//清理线程
class ClearThread extends Thread {
    //每两小时清理一次
    long CLEAR_INTERVAL = 2 * 3600 * 1000;

    @Override
    public void run() {
        while (true) {
            try {
                sleep(CLEAR_INTERVAL);
                Map<String, ECPInstance> instanceMap = EventCorrelationManager.getInstance().getInstanceMap();
                for (ECPInstance instance : instanceMap.values()) {
                    boolean hasMainEvent = true;
                    if (instance.getMainEvent() == null || instance.getMainEvent().getStatus() > 1) {
                        hasMainEvent = false;
                    }
                    //找出已确认的事件
                    instance.removeConfirmdEvent();
                    //主和从事件都没有，则清除
                    if (!hasMainEvent && !instance.hasSubEvent()) {
                        EventCorrelationManager.getInstance().getInstanceMap().remove(instance.getEcp().getId() + "_" + instance.getId());
                    }
                }
            } catch (Exception e) {
                //每次出错无须处理
                e.printStackTrace();
            }
        }
    }
}
